<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // 假设Type对象如之前所提供
      const Type = {
        auto: 0, // 当token_type为auto时，需要根据value的值（如: , { } [ ]）自动判断类型
        colon: 1, // 冒号 :
        comma: 2, // 逗号 ,
        braceLeft: 3, // 左大括号 {
        braceRight: 4, // 右大括号 }
        bracketLeft: 5, // 左中括号 [
        bracketRight: 6, // 右中括号 ]
        keyword: 7, // 关键字 true false null
        number: 8, // 数字 123
        string: 9, // 字符串 "name"
      };

      class Token {
        constructor(tokenType = null, value = null) {
          const d = {
            ":": Type.colon,
            ",": Type.comma,
            "{": Type.braceLeft,
            "}": Type.braceRight,
            "[": Type.bracketLeft,
            "]": Type.bracketRight,
          };

          // 如果tokenType是自动的，则根据value的值确定具体的类型
          if (tokenType === Type.auto) {
            this.type = d[value];
          } else {
            this.type = tokenType; // 否则直接使用传入的tokenType
          }

          this.value = value; // 设置token的值
        }

        toString() {
          // 返回Token的字符串表示形式，假设你想以字符串格式类似于Python的__repr__方法显示token
          const valueString = `"${this.value}"`;
          return `type: ${this.type}, len: ${
            this.value ? this.value.length : 0
          }, value: ${valueString}`;
        }
      }

      // 解析数字直到非数字字符的位置
      function numberEnd(s1, offset) {
        const digits = "1234567890";
        for (let i = 0; i < s1.slice(offset).length; i++) {
          if (!digits.includes(s1[offset + i])) {
            return i;
          }
        }
        console.log("** 错误, 数字解析错误");
        return -1; // 如果整个字符串都是数字，返回-1表示错误
      }

      // 解析字符串直到闭合引号的位置，处理转义字符
      function stringEnd(s1, offset) {
        const bs = {
          b: "\b",
          f: "\f",
          n: "\n",
          r: "\r",
          t: "\t",
          "/": "/",
          '"': '"',
          "\\": "\\",
        };
        let res = "";
        let i = offset;

        while (i < s1.length) {
          const a = s1[i];
          if (a === '"') {
            return { result: res, index: i };
          } else if (a === "\\") {
            const b = s1[i + 1];
            if (b in bs) {
              res += bs[b];
              i += 2;
            } else {
              console.log("** 错误, 不合法的转义字符: ", a + b);
              return { result: "", index: -1 };
            }
          } else {
            res += a;
            i += 1;
          }
        }
        return { result: res, index: i };
      }

      console.log("Test numberEnd with '12345abc': ", numberEnd("12345abc", 0));
      console.log("Test numberEnd with '6789': ", numberEnd("6789", 0));
      console.log("Test numberEnd with '123.456': ", numberEnd("123.456", 0));

      console.log(
        "Test stringEnd with '\"Hello, world!\" rest of string': ",
        stringEnd('"Hello, world!" rest of string', 1)
      );
      console.log(
        'Test stringEnd with \'"Escape \\" sequences" more\': ',
        stringEnd('"Escape \\" sequences" more', 1)
      );
      console.log(
        "Test stringEnd with '\"Invalid \\a escape\"': ",
        stringEnd('"Invalid \\a escape"', 1)
      );
    </script>
  </body>
</html>
